home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Chip 2007 January, February, March & April
/
Chip-Cover-CD-2007-02.iso
/
Pakiet bezpieczenstwa
/
mini Pentoo LiveCD 2006.1
/
mpentoo-2006.1.iso
/
livecd.squashfs
/
usr
/
lib
/
python2.4
/
smtpd.pyc
(
.txt
)
< prev
next >
Wrap
Python Compiled Bytecode
|
2005-10-18
|
16KB
|
555 lines
# Source Generated with Decompyle++
# File: in.pyc (Python 2.4)
"""An RFC 2821 smtp proxy.
Usage: %(program)s [options] [localhost:localport [remotehost:remoteport]]
Options:
--nosetuid
-n
This program generally tries to setuid `nobody', unless this flag is
set. The setuid call will fail if this program is not run as root (in
which case, use this flag).
--version
-V
Print the version number and exit.
--class classname
-c classname
Use `classname' as the concrete SMTP proxy class. Uses `PureProxy' by
default.
--debug
-d
Turn on debugging prints.
--help
-h
Print this message and exit.
Version: %(__version__)s
If localhost is not given then `localhost' is used, and if localport is not
given then 8025 is used. If remotehost is not given then `localhost' is used,
and if remoteport is not given, then 25 is used.
"""
import sys
import os
import errno
import getopt
import time
import socket
import asyncore
import asynchat
__all__ = [
'SMTPServer',
'DebuggingServer',
'PureProxy',
'MailmanProxy']
program = sys.argv[0]
__version__ = 'Python SMTP proxy version 0.2'
class Devnull:
def write(self, msg):
pass
def flush(self):
pass
DEBUGSTREAM = Devnull()
NEWLINE = '\n'
EMPTYSTRING = ''
COMMASPACE = ', '
def usage(code, msg = ''):
print >>sys.stderr, __doc__ % globals()
if msg:
print >>sys.stderr, msg
sys.exit(code)
class SMTPChannel(asynchat.async_chat):
COMMAND = 0
DATA = 1
def __init__(self, server, conn, addr):
asynchat.async_chat.__init__(self, conn)
self._SMTPChannel__server = server
self._SMTPChannel__conn = conn
self._SMTPChannel__addr = addr
self._SMTPChannel__line = []
self._SMTPChannel__state = self.COMMAND
self._SMTPChannel__greeting = 0
self._SMTPChannel__mailfrom = None
self._SMTPChannel__rcpttos = []
self._SMTPChannel__data = ''
self._SMTPChannel__fqdn = socket.getfqdn()
self._SMTPChannel__peer = conn.getpeername()
print >>DEBUGSTREAM, 'Peer:', repr(self._SMTPChannel__peer)
self.push('220 %s %s' % (self._SMTPChannel__fqdn, __version__))
self.set_terminator('\r\n')
def push(self, msg):
asynchat.async_chat.push(self, msg + '\r\n')
def collect_incoming_data(self, data):
self._SMTPChannel__line.append(data)
def found_terminator(self):
line = EMPTYSTRING.join(self._SMTPChannel__line)
print >>DEBUGSTREAM, 'Data:', repr(line)
self._SMTPChannel__line = []
if self._SMTPChannel__state == self.COMMAND:
if not line:
self.push('500 Error: bad syntax')
return None
method = None
i = line.find(' ')
if i < 0:
command = line.upper()
arg = None
else:
command = line[:i].upper()
arg = line[i + 1:].strip()
method = getattr(self, 'smtp_' + command, None)
if not method:
self.push('502 Error: command "%s" not implemented' % command)
return None
method(arg)
return None
elif self._SMTPChannel__state != self.DATA:
self.push('451 Internal confusion')
return None
data = []
for text in line.split('\r\n'):
if text and text[0] == '.':
data.append(text[1:])
continue
data.append(text)
self._SMTPChannel__data = NEWLINE.join(data)
status = self._SMTPChannel__server.process_message(self._SMTPChannel__peer, self._SMTPChannel__mailfrom, self._SMTPChannel__rcpttos, self._SMTPChannel__data)
self._SMTPChannel__rcpttos = []
self._SMTPChannel__mailfrom = None
self._SMTPChannel__state = self.COMMAND
self.set_terminator('\r\n')
if not status:
self.push('250 Ok')
else:
self.push(status)
def smtp_HELO(self, arg):
if not arg:
self.push('501 Syntax: HELO hostname')
return None
if self._SMTPChannel__greeting:
self.push('503 Duplicate HELO/EHLO')
else:
self._SMTPChannel__greeting = arg
self.push('250 %s' % self._SMTPChannel__fqdn)
def smtp_NOOP(self, arg):
if arg:
self.push('501 Syntax: NOOP')
else:
self.push('250 Ok')
def smtp_QUIT(self, arg):
self.push('221 Bye')
self.close_when_done()
def __getaddr(self, keyword, arg):
address = None
keylen = len(keyword)
if arg[:keylen].upper() == keyword:
address = arg[keylen:].strip()
if not address:
pass
elif address[0] == '<' and address[-1] == '>' and address != '<>':
address = address[1:-1]
return address
def smtp_MAIL(self, arg):
print >>DEBUGSTREAM, '===> MAIL', arg
address = self._SMTPChannel__getaddr('FROM:', arg)
if not address:
self.push('501 Syntax: MAIL FROM:<address>')
return None
if self._SMTPChannel__mailfrom:
self.push('503 Error: nested MAIL command')
return None
self._SMTPChannel__mailfrom = address
print >>DEBUGSTREAM, 'sender:', self._SMTPChannel__mailfrom
self.push('250 Ok')
def smtp_RCPT(self, arg):
print >>DEBUGSTREAM, '===> RCPT', arg
if not self._SMTPChannel__mailfrom:
self.push('503 Error: need MAIL command')
return None
address = self._SMTPChannel__getaddr('TO:', arg)
if not address:
self.push('501 Syntax: RCPT TO: <address>')
return None
self._SMTPChannel__rcpttos.append(address)
print >>DEBUGSTREAM, 'recips:', self._SMTPChannel__rcpttos
self.push('250 Ok')
def smtp_RSET(self, arg):
if arg:
self.push('501 Syntax: RSET')
return None
self._SMTPChannel__mailfrom = None
self._SMTPChannel__rcpttos = []
self._SMTPChannel__data = ''
self._SMTPChannel__state = self.COMMAND
self.push('250 Ok')
def smtp_DATA(self, arg):
if not self._SMTPChannel__rcpttos:
self.push('503 Error: need RCPT command')
return None
if arg:
self.push('501 Syntax: DATA')
return None
self._SMTPChannel__state = self.DATA
self.set_terminator('\r\n.\r\n')
self.push('354 End data with <CR><LF>.<CR><LF>')
class SMTPServer(asyncore.dispatcher):
def __init__(self, localaddr, remoteaddr):
self._localaddr = localaddr
self._remoteaddr = remoteaddr
asyncore.dispatcher.__init__(self)
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
self.set_reuse_addr()
self.bind(localaddr)
self.listen(5)
print >>DEBUGSTREAM, '%s started at %s\n\tLocal addr: %s\n\tRemote addr:%s' % (self.__class__.__name__, time.ctime(time.time()), localaddr, remoteaddr)
def handle_accept(self):
(conn, addr) = self.accept()
print >>DEBUGSTREAM, 'Incoming connection from %s' % repr(addr)
channel = SMTPChannel(self, conn, addr)
def process_message(self, peer, mailfrom, rcpttos, data):
"""Override this abstract method to handle messages from the client.
peer is a tuple containing (ipaddr, port) of the client that made the
socket connection to our smtp port.
mailfrom is the raw address the client claims the message is coming
from.
rcpttos is a list of raw addresses the client wishes to deliver the
message to.
data is a string containing the entire full text of the message,
headers (if supplied) and all. It has been `de-transparencied'
according to RFC 821, Section 4.5.2. In other words, a line
containing a `.' followed by other text has had the leading dot
removed.
This function should return None, for a normal `250 Ok' response;
otherwise it returns the desired response string in RFC 821 format.
"""
raise NotImplementedError
class DebuggingServer(SMTPServer):
def process_message(self, peer, mailfrom, rcpttos, data):
inheaders = 1
lines = data.split('\n')
print '---------- MESSAGE FOLLOWS ----------'
for line in lines:
if inheaders and not line:
print 'X-Peer:', peer[0]
inheaders = 0
print line
print '------------ END MESSAGE ------------'
class PureProxy(SMTPServer):
def process_message(self, peer, mailfrom, rcpttos, data):
lines = data.split('\n')
i = 0
for line in lines:
if not line:
break
i += 1
lines.insert(i, 'X-Peer: %s' % peer[0])
data = NEWLINE.join(lines)
refused = self._deliver(mailfrom, rcpttos, data)
print >>DEBUGSTREAM, 'we got some refusals:', refused
def _deliver(self, mailfrom, rcpttos, data):
import smtplib as smtplib
refused = { }
try:
s = smtplib.SMTP()
s.connect(self._remoteaddr[0], self._remoteaddr[1])
try:
refused = s.sendmail(mailfrom, rcpttos, data)
finally:
s.quit()
except smtplib.SMTPRecipientsRefused:
e = None
print >>DEBUGSTREAM, 'got SMTPRecipientsRefused'
refused = e.recipients
except (socket.error, smtplib.SMTPException):
e = None
print >>DEBUGSTREAM, 'got', e.__class__
errcode = getattr(e, 'smtp_code', -1)
errmsg = getattr(e, 'smtp_error', 'ignore')
for r in rcpttos:
refused[r] = (errcode, errmsg)
return refused
class MailmanProxy(PureProxy):
def process_message(self, peer, mailfrom, rcpttos, data):
StringIO = StringIO
import cStringIO
Utils = Utils
import Mailman
Message = Message
import Mailman
MailList = MailList
import Mailman
listnames = []
for rcpt in rcpttos:
local = rcpt.lower().split('@')[0]
parts = local.split('-')
if len(parts) > 2:
continue
listname = parts[0]
if len(parts) == 2:
command = parts[1]
else:
command = ''
if not Utils.list_exists(listname) or command not in ('', 'admin', 'owner', 'request', 'join', 'leave'):
continue
listnames.append((rcpt, listname, command))
for rcpt, listname, command in listnames:
rcpttos.remove(rcpt)
print >>DEBUGSTREAM, 'forwarding recips:', ' '.join(rcpttos)
if rcpttos:
refused = self._deliver(mailfrom, rcpttos, data)
print >>DEBUGSTREAM, 'we got refusals:', refused
mlists = { }
s = StringIO(data)
msg = Message.Message(s)
if not msg.getheader('from'):
msg['From'] = mailfrom
if not msg.getheader('date'):
msg['Date'] = time.ctime(time.time())
for rcpt, listname, command in listnames:
print >>DEBUGSTREAM, 'sending message to', rcpt
mlist = mlists.get(listname)
if not mlist:
mlist = MailList.MailList(listname, lock = 0)
mlists[listname] = mlist
if command == '':
msg.Enqueue(mlist, tolist = 1)
continue
if command == 'admin':
msg.Enqueue(mlist, toadmin = 1)
continue
if command == 'owner':
msg.Enqueue(mlist, toowner = 1)
continue
if command == 'request':
msg.Enqueue(mlist, torequest = 1)
continue
if command in ('join', 'leave'):
if command == 'join':
msg['Subject'] = 'subscribe'
else:
msg['Subject'] = 'unsubscribe'
msg.Enqueue(mlist, torequest = 1)
continue
class Options:
setuid = 1
classname = 'PureProxy'
def parseargs():
global DEBUGSTREAM
try:
(opts, args) = getopt.getopt(sys.argv[1:], 'nVhc:d', [
'class=',
'nosetuid',
'version',
'help',
'debug'])
except getopt.error:
e = None
usage(1, e)
options = Options()
for opt, arg in opts:
if opt in ('-h', '--help'):
usage(0)
continue
if opt in ('-V', '--version'):
print >>sys.stderr, __version__
sys.exit(0)
continue
if opt in ('-n', '--nosetuid'):
options.setuid = 0
continue
if opt in ('-c', '--class'):
options.classname = arg
continue
if opt in ('-d', '--debug'):
DEBUGSTREAM = sys.stderr
continue
if len(args) < 1:
localspec = 'localhost:8025'
remotespec = 'localhost:25'
elif len(args) < 2:
localspec = args[0]
remotespec = 'localhost:25'
elif len(args) < 3:
localspec = args[0]
remotespec = args[1]
else:
usage(1, 'Invalid arguments: %s' % COMMASPACE.join(args))
i = localspec.find(':')
if i < 0:
usage(1, 'Bad local spec: %s' % localspec)
options.localhost = localspec[:i]
try:
options.localport = int(localspec[i + 1:])
except ValueError:
usage(1, 'Bad local port: %s' % localspec)
i = remotespec.find(':')
if i < 0:
usage(1, 'Bad remote spec: %s' % remotespec)
options.remotehost = remotespec[:i]
try:
options.remoteport = int(remotespec[i + 1:])
except ValueError:
usage(1, 'Bad remote port: %s' % remotespec)
return options
if __name__ == '__main__':
options = parseargs()
if options.setuid:
try:
import pwd
except ImportError:
print >>sys.stderr, 'Cannot import module "pwd"; try running with -n option.'
sys.exit(1)
nobody = pwd.getpwnam('nobody')[2]
try:
os.setuid(nobody)
except OSError:
e = None
if e.errno != errno.EPERM:
raise
print >>sys.stderr, 'Cannot setuid "nobody"; try running with -n option.'
sys.exit(1)
except:
None<EXCEPTION MATCH>OSError
None<EXCEPTION MATCH>OSError
classname = options.classname
if '.' in classname:
lastdot = classname.rfind('.')
mod = __import__(classname[:lastdot], globals(), locals(), [
''])
classname = classname[lastdot + 1:]
else:
import __main__ as mod
class_ = getattr(mod, classname)
proxy = class_((options.localhost, options.localport), (options.remotehost, options.remoteport))
try:
asyncore.loop()
except KeyboardInterrupt:
pass
except:
None<EXCEPTION MATCH>KeyboardInterrupt
None<EXCEPTION MATCH>KeyboardInterrupt